package com.kehutong.wwin.service.service;

import com.kehutong.common.util.DateUtil;
import com.kehutong.common.util.Token;
import com.kehutong.wwin.service.entity.Corp;
import com.kehutong.wwin.service.entity.ResidentMap;
import com.kehutong.wwin.service.entity.EmployeeMap;
import com.kehutong.wwin.service.entity.TagMap;
import com.kehutong.wwin.service.enums.Gender;
import com.kehutong.wwin.service.util.WwInHttpClient;
import com.kehutong.wxapi.request.AddMsgTemplateRequest;
import com.kehutong.wxapi.request.BatchGetByUserRequest;
import com.kehutong.wxapi.request.ExternalContactGetRequest;
import com.kehutong.wxapi.request.FollowUserListRequest;
import com.kehutong.wxapi.response.AddMsgTemplateResponse;
import com.kehutong.wxapi.response.BatchGetByUserResponse;
import com.kehutong.wxapi.response.ExternalContactGetResponse;
import com.kehutong.wxapi.response.FollowUserListResponse;
import com.kehutong.wxapi.service.ExternalContactService;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSON;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.JSONResult;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.connection.ThreadLocalCache;
import org.coraframework.orm.util.Enums;
import org.coraframework.util.IDGenerate;
import org.coraframework.util.Objects;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 企业微信客户事件同步到客户通住户服务类
 *
 * @author: liukunlong
 * @date: 2021-03-11 09:20
 */
@WebService("/wwin/event/change_external_contact")
public class ToKhtResidentService {

    static final Logger logger = LoggerFactory.getLogger(ToKhtDepartmentService.class);

    @Inject
    private WwInHttpClient httpClient;

    @Inject
    private JdbcSession jdbcSession;

    @Inject
    private CorpService corpService;

    @Inject
    private ExternalContactService externalContactService;

    @Inject
    private ToKhtTagService toKhtTagService;


    /**
     * 收到添加企业客户事件后添加住户信息
     * 配置了客户联系功能的成员添加外部联系人时，回调该事件
     * 企业可以根据ExternalUserID调用“获取客户详情”读取详情。
     * 企业可以通过配置客户联系「联系我」方式接口来指定State参数，当有客户通过这个联系方式添加企业成员时会回调此参数。
     * 注意:如果外部联系人和成员已经开始聊天或已通过「外部联系人免验证添加成员事件」得到的welcomecode发送欢迎语，则不会继续返回welcomecode。
     *
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    @ReqMapping("/add_external_contact")
    public Object addExternalContact(JSONObject wwJson) throws Exception {
        String cropId=wwJson.getString("ToUserName");
        Corp crop = Pool.get(Corp.class, cropId);
        if (Objects.isNull(crop)) {
            logger.error("公司内建信息不存在,{}",wwJson);
            return Result.success();
        }
        Token token=Token.create();
        token.setCompanyNo(crop.getKhtid());
        return saveOrUpdateResident(token, wwJson);
    }

    /**
     * 保存或更新住户信息
     *
     * @param token  用户信息
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    public Object saveOrUpdateResident(Token token, JSONObject wwJson) throws Exception {
        String externalUserId = wwJson.getString("ExternalUserID");
        //查询客户通是否存在住户信息
        ThreadLocalCache.current().setCorpId(token.getCompanyNo());
       /* ResidentMap residentMap = getCustomerById(externalUserId);
        if (Objects.isNull(residentMap)) {
            residentMap = Pool.newInstance(ResidentMap.class, externalUserId);
            residentMap.setKhtid(IDGenerate.uuid());
            jdbcSession.insert(residentMap);
        }*/
        ExternalContactGetRequest externalContactGetRequest = new ExternalContactGetRequest();
        externalContactGetRequest.setAccessToken(httpClient.getContactAccessToken(token));
        externalContactGetRequest.setExternalUserid(externalUserId);
        ExternalContactGetResponse externalContactGetResponse = externalContactService.getExternalContact(externalContactGetRequest);
        if (externalContactGetResponse.getErrcode() != 0) {
            return Result.error(externalContactGetResponse.getErrcode(), externalContactGetResponse.getErrmsg());
        }

        //联系人信息
        ExternalContactGetResponse.ExternalContactDTO externalContact = externalContactGetResponse.getExternalContact();

        //外部联系人的类型，1表示该外部联系人是微信用户，2表示该外部联系人是企业微信用户,暂时忽略外部联系人是企业的用户
        Integer type=externalContact.getType();
        if(type==2){
            logger.info("加入第三方外部联系人,联系人类型是企业微信,进行忽略：{}",externalContact.toString());
            return Result.success();
        }
        String unionid=externalContact.getUnionid();
        JSONObject accountJson=new JSONObject();
        accountJson.put("id",IDGenerate.uuid());
        accountJson.put("realname",externalContact.getName());
        accountJson.put("unionid",unionid);
        accountJson.put("externalUserId",externalUserId);
        JSONObject accountJsonObject=saveOrUpdateAccount(accountJson,token);
        if (Objects.isEmpty(accountJsonObject)) {
            logger.error("同步第三方外部联系人创建账户信息错误：{}",accountJsonObject);
            return Result.success();
        }

        //性能优化不用每次都要查询映射信息
        //ResidentMap ResidentMap = getCustomerById(externalUserId);
        ResidentMap residentMap = getCustomerById(externalUserId);
        if (Objects.isNull(residentMap)) {
            residentMap = Pool.newInstance(ResidentMap.class, externalUserId);
            logger.info("客户联系同步账号返回的账号数据,{}",accountJsonObject.toJSONString());
            String accountNo = accountJsonObject.getString("id");
            residentMap.setKhtid(accountNo);
            residentMap.setUnionid(unionid);
            jdbcSession.insert(residentMap);
        }


        //处理联系人的跟进人信息
        List<ExternalContactGetResponse.FollowUserDTO> followUserList = externalContactGetResponse.getFollowUser();
        if (Objects.nonEmpty(followUserList)) {
            //todo 可能出现没有员工情况
            Map<String,String> employeeMapping=batchGetEmployee();
            JSONArray residentList = new JSONArray();
            for (ExternalContactGetResponse.FollowUserDTO followInfo : followUserList) {
                JSONObject jsonObject = new JSONObject();
                //跟进人微信ID转换客户通员工ID,可能出现为空情况,忽略当前跟进人
                String userId=employeeMapping.get(followInfo.getUserid());
                if(Objects.isEmpty(userId)){
                    continue;
                }
                jsonObject.put("id", residentMap.getKhtid());
                jsonObject.put("avatar", externalContact.getAvatar());
                jsonObject.put("corpName", externalContact.getCorpName());
                jsonObject.put("userId",userId);
                jsonObject.put("nickname",externalContact.getName());
                if (Objects.nonNull(externalContact.getGender())) {
                    Gender gender = Enums.getEnum(Gender.class, externalContact.getGender().toString());
                    JSONObject genderJson = new JSONObject();
                    genderJson.put("id", gender.getId());
                    genderJson.put("desc", gender.getDesc());
                    jsonObject.put("gender", genderJson.toJSONString());

                    List<String> remarkMobiles=followInfo.getRemarkMobiles();
                    //该成员对此客户备注的手机号码，第三方不可获取
                    if(Objects.nonEmpty(remarkMobiles)){
                        jsonObject.put("mobile",remarkMobiles.get(0));
                    }

                    //企业微信标签编号转换成客户通标签编号，如果当前微信标签没有映射信息则同步微信标签数据然后再次获取客户通标签编号
                    List<ExternalContactGetResponse.FollowUserDTO.TagsDTO> wxTags = followInfo.getTags();
                    List<String> tagIds = new ArrayList<>();
                    if (Objects.nonEmpty(wxTags)) {
                        for (ExternalContactGetResponse.FollowUserDTO.TagsDTO wxTag : wxTags) {
                            //如果标签类型是用户自定义忽略标签
                            if(wxTag.getType()==2){
                                continue;
                            }
                            TagMap tagMap = toKhtTagService.getTagById(wxTag.getTagId());
                            if (Objects.isNull(tagMap)) {
                                toKhtTagService.syncTag(token, "tag", wxTag.getTagId());
                                tagMap = toKhtTagService.getTagById(wxTag.getTagId());

                            }
                            tagIds.add(tagMap.getKhtid());
                        }
                        jsonObject.put("tagIds", JSONArray.parseArray(JSON.toJSONString(tagIds)));
                    }

                    //添加住户数据到数组中
                    residentList.add(jsonObject);
                }
            }
            //批量新增员工跟进的住户信息
            JSONObject jsonRs = httpClient.postKht("/crm/resident/service/batchSaveOrUpdateResident",token, http -> {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("residentList", residentList);
                http.setBody(jsonObject.toJSONString());
            });
            return Result.error(jsonRs.getIntValue("code"), jsonRs.getString("message"));
        }
        return Result.success();
    }

    /**
     * 收到编辑企业客户事件后更新住户信息
     * 配置了客户联系功能的成员修改外部联系人的备注、手机号或标签时，回调该事件
     *
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    @ReqMapping("/edit_external_contact")
    public Object editExternalContact(JSONObject wwJson) throws Exception {
        String cropId=wwJson.getString("ToUserName");
        Corp crop = Pool.get(Corp.class, cropId);
        if (Objects.isNull(crop)) {
            logger.error("公司内建信息不存在,{}",wwJson);
            return Result.success();
        }
        Token token=Token.create();
        token.setCompanyNo(crop.getKhtid());
        logger.info("收到编辑企业客户事件后更新住户信息..............................");
        return saveOrUpdateResident(token, wwJson);
    }

    /**
     * 收到外部联系人免验证添加成员事件后发送欢迎语?
     * 外部联系人添加了配置了客户联系功能且开启了免验证的成员时（此时成员尚未确认添加对方为好友），回调该事件
     * 企业可以根据ExternalUserID调用“获取客户详情”读取详情。
     * 企业可以通过配置客户联系「联系我」方式接口来指定State参数，当有客户通过这个联系方式添加企业成员时会回调此参数。
     * 注意:如果外部联系人和成员已经开始聊天，则不会返回welcomecode。
     *
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    @ReqMapping("/add_half_external_contact")
    public Object addHalfExternalContact(JSONObject wwJson) throws Exception {
        String cropId=wwJson.getString("ToUserName");
        Corp crop = Pool.get(Corp.class, cropId);
        if (Objects.isNull(crop)) {
            logger.error("公司内建信息不存在,{}",wwJson);
            return Result.success();
        }
        Token token=Token.create();
        token.setCompanyNo(crop.getKhtid());

        logger.info("收到外部联系人免验证添加成员事件后发送欢迎语?..............................");
        return saveOrUpdateResident(token, wwJson);
    }


    /**
     * 收到删除企业客户事件后删除住户信息跟进人相关信息
     * 配置了客户联系功能的成员删除外部联系人时，回调该事件
     * <p>
     * 删除住户中跟进人相关信息
     *
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    @ReqMapping("/del_external_contact")
    public Object delExternalContact(JSONObject wwJson) throws Exception {
        String cropId=wwJson.getString("ToUserName");
        Corp crop = Pool.get(Corp.class, cropId);
        if (Objects.isNull(crop)) {
            logger.error("公司内建信息不存在,{}",wwJson);
            return Result.success();
        }



        String externalUserId = wwJson.getString("ExternalUserID");
        String userId = wwJson.getString("UserID");
        //查询客户通是否存在住户信息
        ThreadLocalCache.current().setCorpId(crop.getKhtid());
        ResidentMap residentMap = getCustomerById(externalUserId);
        if(Objects.nonNull(residentMap)){
            //删除住户跟进人信息
            JSONObject jsonRs = httpClient.postKht("/crm/resident/service/deleteResidentUser",crop.getKhtid(), http -> {
                http.addParam("id", residentMap.getKhtid());
                http.addParam("userId",getEmployeeByWwId(userId).getKhtid());
            });
            return Result.error(jsonRs.getIntValue("code"), jsonRs.getString("message"));
        }
        return Result.success();
    }

    /**
     * 收到删除跟进成员事件后删除住户信息跟进人相关信息
     * 配置了客户联系功能的成员被外部联系人删除时，回调该事件
     *
     * @param token  用户信息
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    @ReqMapping("/del_follow_user")
    public Object delFollowUser(Token token, JSONObject wwJson) throws Exception {
        String cropId=wwJson.getString("ToUserName");
        Corp crop = Pool.get(Corp.class, cropId);
        if (Objects.isNull(crop)) {
            logger.error("公司内建信息不存在,{}",wwJson);
            return Result.success();
        }
        String externalUserId = wwJson.getString("ExternalUserID");
        String userId = wwJson.getString("UserID");
        //查询客户通是否存在住户信息
        ThreadLocalCache.current().setCorpId(crop.getKhtid());
        ResidentMap residentMap = getCustomerById(externalUserId);
        if(Objects.nonNull(residentMap)){
            //删除住户跟进人信息
            JSONObject jsonRs = httpClient.postKht("/crm/resident/service/deleteResidentUser", crop.getKhtid(), http -> {
                http.addParam("id", residentMap.getKhtid());
                http.addParam("userId",getEmployeeByWwId(userId).getKhtid());
            });
            return Result.error(jsonRs.getIntValue("code"), jsonRs.getString("message"));
        }
        return Result.success();
    }

    /**
     * 收到客户接替失败事件?
     * 企业将客户分配给新的成员接替后，客户添加失败时回调该事件
     * 如果此客户在企业内仍有其他在职的跟进人，则企业仍可以根据ExternalUserID调用“获取客户详情”读取详情，否则无法获取。
     *
     * @param wwJson 微信事件Json对象
     * @return 结果对象
     * @throws Exception 异常
     */
    @ReqMapping("/transfer_fail")
    public Object transferFail(JSONObject wwJson) throws Exception {
        return Result.success();
    }

    /**
     * 获取用户跟进人信息
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @ReqMapping("/get/message/context")
    public Object getMessageContext(JSONObject jsonObject) throws Exception {
        String id=jsonObject.getString("id");
        JSONArray userIdsJsonArray = jsonObject.getJSONArray("userIds");
        Map<String,Object> result=new LinkedHashMap<>();
        List<EmployeeMap> employeeMapList=new ArrayList<>();
        ResidentMap dbResidentMap=jdbcSession.findOne(ResidentMap.class).eq("khtid",id).exe(false);
        if(Objects.isNull(dbResidentMap)){
            result.put("customerUserId","");
            result.put("employeeUserId",employeeMapList);
            return Result.success(result);
        }
        if (Objects.isEmpty(userIdsJsonArray)) {
            result.put("customerUserId",dbResidentMap.getId());
            result.put("employeeUserId",employeeMapList);
            return Result.success(result);
        }

        //根据外部联系人ID集合查询出存在的映射信息
        employeeMapList = jdbcSession.findArray(EmployeeMap.class)
                .in("khtid",userIdsJsonArray)
                .exe(false);
        if(Objects.isEmpty(employeeMapList)){
            result.put("customerUserId",dbResidentMap.getId());
            result.put("employeeUserId",employeeMapList);
            return Result.success(result);
        }
        List<String> employeeUserId = employeeMapList.stream().map(EmployeeMap::getUserId).collect(Collectors.toList());
        result.put("customerUserId",dbResidentMap.getId());
        result.put("employeeUserId",employeeUserId);
        return Result.success(result);
    }

    /**
     * 根据微信标志获取映射信息
     *
     * @param id 微信标志
     * @return 映射信息
     */
    public ResidentMap getCustomerById(String id) {
        return Pool.get(ResidentMap.class, id);
    }


    /**
     * 批量获取符合条件的映射信息()
     * @param externalContactList 微信返回的外部联系人集合
     * @return 符合条件的映射信息
     */
    public Map<String, ResidentMap> batchGetCustomer(List<BatchGetByUserResponse.ExternalContactListDTO> externalContactList) {
        //外部联系人ID与客户映射对象
        Map<String, ResidentMap> mapping=new HashMap<>();
        if(Objects.isEmpty(externalContactList)){
            return mapping;
        }
        //获取所有外部联系人ID集合
        List<String> ids=new ArrayList<>();
        externalContactList.forEach(val->{
            ids.add(val.getExternalContact().getExternalUserid());
        });
        //根据外部联系人ID集合查询出存在的映射信息
        final List<ResidentMap> residentMapList = jdbcSession.findArray(ResidentMap.class)
                .in("id",ids)
                .exe();
        //把信息转换成map返回出来
        mapping= residentMapList.stream().collect(Collectors.toMap(ResidentMap::getId, residentMap -> residentMap));
        return mapping;
    }

    /**
     * 批量获取符合条件的员工映射信息
     * @return 符合条件的映射信息
     */
    public Map<String,String> batchGetEmployee() {
        //外部联系人ID与客户映射对象
        Map<String,String> mapping=new HashMap<>();
        //根据外部联系人ID集合查询出存在的映射信息
        final List<EmployeeMap> employeeMapList = jdbcSession.findArray(EmployeeMap.class)
                .exe();
        //把信息转换成map返回出来
        mapping= employeeMapList.stream().collect(Collectors.toMap(EmployeeMap::getUserId,EmployeeMap::getKhtid));
        return mapping;
    }


    /**
     * 构建客户映射对象
     *
     * @param wwJson 微信事件Json对象
     * @return 客户映射对象
     */
    protected ResidentMap buildCustomer(JSONObject wwJson) {
        ResidentMap residentMap = Pool.newInstance(ResidentMap.class, wwJson.getString("ExternalUserID"));
        residentMap.setKhtid(IDGenerate.uuid());
        return residentMap;
    }


    /**
     * 同步住户数据
     * 每企业调用单个cgi/api不可超过1万次/分(1秒最多调用166次,一次请求必须大于6毫秒)，15万次/小时(1秒最多调用41次,一次请求必须大于24毫秒)
     * 每ip调用单个 cgi/api不可超过2万次/分(1秒最多调用333次)，60万次/小时(1秒最多调用166次)
     * 接口本地测试100毫秒一次
     * 第三方应用提供商每ip调用单个cgi/api不可超过4万次/分，120万次/小时
     * @param token 用户信息
     * @return 成功对象
     * @throws Exception 异常
     */
    public Object syncResident(Token token) throws Exception {
        //获取配置了客户联系功能的成员列表
        String accessToken = httpClient.getContactAccessToken(token);
        FollowUserListRequest followUserListRequest = new FollowUserListRequest();
        followUserListRequest.setAccessToken(accessToken);
        FollowUserListResponse followUserListResponse = externalContactService.getFollowUserList(followUserListRequest);
        if (followUserListResponse.getErrcode() != 0) {
            return Result.error(followUserListResponse.getErrcode(), followUserListResponse.getErrmsg());
        }
        List<String> followUserList = followUserListResponse.getFollowUser();
        if (Objects.nonEmpty(followUserList)) {
            //todo 可能出现没有员工情况
            Map<String,String> employeeMapping=batchGetEmployee();
            for (String followUser : followUserList) {
                //跟进人微信ID转换客户通员工ID,可能出现为空情况,忽略当前跟进人
                String userId=employeeMapping.get(followUser);
                if(Objects.isEmpty(userId)){
                    continue;
                }

                //获取指定成员(员工)的客户详情信息列表
                List<BatchGetByUserResponse.ExternalContactListDTO> externalContactList = getExternalContactList(token, followUser);
                if (Objects.nonEmpty(externalContactList)) {
                    JSONArray residentList = new JSONArray();
                    //批量新增微信与客户通住户映射数据集合
                    List<ResidentMap> batchAddResidentMapList=new ArrayList<>();

                    //获取已有外部联系人ID的映射关系(性能优化提高查询效率)
                    Map<String,ResidentMap> wxToResidentMapMapping=batchGetCustomer(externalContactList);
                    for (BatchGetByUserResponse.ExternalContactListDTO externalContactListDTO : externalContactList) {
                        BatchGetByUserResponse.ExternalContactListDTO.ExternalContactDTO externalContact = externalContactListDTO.getExternalContact();
                        //外部联系人的类型，1表示该外部联系人是微信用户，2表示该外部联系人是企业微信用户,暂时忽略外部联系人是企业的用户
                        Integer type=externalContact.getType();
                        if(type==2){
                            logger.info("同步第三方外部联系人,联系人类型是企业微信,进行忽略：{}",externalContact.toString());
                            continue;
                        }


                        logger.info("外部联系人信息：{}",JSON.toJSON(externalContact).toString());
                        String externalUserId = externalContact.getExternalUserid();
                        String unionid=externalContact.getUnionid();
                        JSONObject accountJson=new JSONObject();
                        accountJson.put("id",IDGenerate.uuid());
                        accountJson.put("realname",externalContact.getName());
                        accountJson.put("unionid",unionid);
                        accountJson.put("externalUserId",externalUserId);

                        JSONObject accountJsonObject=saveOrUpdateAccount(accountJson,token);
                        if (Objects.isEmpty(accountJsonObject)) {
                            logger.error("同步第三方外部联系人创建账户信息错误：{}",accountJsonObject);
                            continue;
                        }

                        //性能优化不用每次都要查询映射信息
                        //ResidentMap ResidentMap = getCustomerById(externalUserId);
                        ResidentMap residentMap = wxToResidentMapMapping.get(externalUserId);
                        if (Objects.isNull(residentMap)) {
                            residentMap = Pool.newInstance(ResidentMap.class, externalUserId);
                            logger.info("客户联系同步账号返回的账号数据,{}",accountJsonObject.toJSONString());
                            String accountNo = accountJsonObject.getString("id");
                            residentMap.setKhtid(accountNo);
                            residentMap.setUnionid(unionid);
                            //residentMap.setKhtid(IDGenerate.uuid());
                            //修改为批量插入没有映射的数据提高性能
                            //jdbcSession.insert(ResidentMap);
                            batchAddResidentMapList.add(residentMap);
                        }

                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("id", residentMap.getKhtid());
                        jsonObject.put("avatar", Objects.isNull(externalContact.getAvatar())?accountJsonObject.getString("avatar"):externalContact.getAvatar());
                        jsonObject.put("corpName", externalContact.getCorpName());
                        jsonObject.put("userId", userId);
                        jsonObject.put("nickname",externalContact.getName());
                        if (Objects.nonNull(externalContact.getGender())) {
                            Gender gender = Enums.getEnum(Gender.class, externalContact.getGender().toString());
                            JSONObject genderJson = new JSONObject();
                            genderJson.put("id", gender.getId());
                            genderJson.put("desc", gender.getDesc());
                            jsonObject.put("gender", genderJson.toJSONString());
                        }
                        BatchGetByUserResponse.ExternalContactListDTO.FollowInfoDTO followInfo = externalContactListDTO.getFollowInfo();
                        List<String> remarkMobiles=followInfo.getRemarkMobiles();
                        //该成员对此客户备注的手机号码，第三方不可获取
                        if(Objects.nonEmpty(remarkMobiles)){
                            jsonObject.put("mobile",remarkMobiles.get(0));
                        }else{
                            jsonObject.put("mobile",accountJsonObject.getString("mobile"));
                        }
                        //企业微信标签编号转换成客户通标签编号，如果当前微信标签没有映射信息则同步微信标签数据然后再次获取客户通标签编号(个人标签不会返回)
                        List<String> wxTagIds = followInfo.getTagId();
                        List<String> tagIds = new ArrayList<>();
                        if (Objects.nonEmpty(wxTagIds)) {
                            for (String wxTagId : wxTagIds) {
                                TagMap tagMap = toKhtTagService.getTagById(wxTagId);
                                if (Objects.isNull(tagMap)) {
                                    toKhtTagService.syncTag(token, "tag", wxTagId);
                                    tagMap = toKhtTagService.getTagById(wxTagId);

                                }
                                tagIds.add(tagMap.getKhtid());
                            }
                            jsonObject.put("tagIds", JSONArray.parseArray(JSON.toJSONString(tagIds)));
                        }

                        //添加住户数据到数组中
                        residentList.add(jsonObject);
                    }

                    //批量插入腾讯与客户通没有映射的住户信息
                    if(Objects.nonEmpty(batchAddResidentMapList)){
                        jdbcSession.insert(batchAddResidentMapList);
                    }
                    logger.info("batchSaveOrUpdateResident:{}",residentList);
                    //批量新增员工跟进的住户信息

                    httpClient.postKht("/crm/resident/service/batchSaveOrUpdateResident",token, http -> {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("residentList", residentList);
                        http.setBody(jsonObject.toJSONString());
                    });

                }
            }
        }

        return Result.success();
    }


    /**
     * 新增或更新账户信息
     * 1.住户编号与账户编号一致
     * @param residentJson
     * @return
     * @throws Exception
     */
    private JSONObject saveOrUpdateAccount(JSONObject residentJson,Token token) throws Exception {
        String accountNo = "";
        JSONObject saveOrUpdateAccountResult = httpClient.postKht("/auth/account/service/saveOrUpdateAccount",token.getCompanyNo(), http -> {
            List<String> khtIds = new ArrayList<>();
            khtIds.add(token.getCompanyNo());
            residentJson.put("khtIds", khtIds);
            http.setBody(residentJson.toJSONString());
        });
        if (saveOrUpdateAccountResult.getIntValue("code") != 200) {
            logger.error("ResidentService.saveOrUpdateAccount 新增或更住户对应的账户信息.后续修复数据一致性");
        }
        return saveOrUpdateAccountResult.getJSONObject("data");
    }


    /**
     * 批量获取客户详情
     *
     * @param token  用户信息
     * @param userid 企业成员的userid，字符串类型
     * @return 客户详情集合
     * @throws Exception 异常
     */
    public List<BatchGetByUserResponse.ExternalContactListDTO> getExternalContactList(Token token, String userid) throws Exception {
        String accessToken = httpClient.getContactAccessToken(token);
        List<BatchGetByUserResponse.ExternalContactListDTO> externalContactList = new ArrayList<>();
        BatchGetByUserRequest batchGetByUserRequest = new BatchGetByUserRequest();
        batchGetByUserRequest.setAccessToken(accessToken);
        batchGetByUserRequest.setUserid(userid);
        batchGetByUserRequest.setLimit(100);
        batchGetByUser(externalContactList, batchGetByUserRequest);
        return externalContactList;
    }

    /**
     * 递归请求批量获取客户详情接口
     *
     * @param externalContactList   客户的基本信息集合
     * @param batchGetByUserRequest 批量获取客户详情请求对象
     * @throws Exception 异常
     */
    private void batchGetByUser(List<BatchGetByUserResponse.ExternalContactListDTO> externalContactList, BatchGetByUserRequest batchGetByUserRequest) throws Exception {
        if (Objects.nonNull(batchGetByUserRequest)) {
            BatchGetByUserResponse batchGetByUserResponse = externalContactService.batchGetByUser(batchGetByUserRequest);
            if (batchGetByUserResponse.getErrcode() == 0) {
                List<BatchGetByUserResponse.ExternalContactListDTO> reqExternalContactList = batchGetByUserResponse.getExternalContactList();
                if (Objects.nonEmpty(reqExternalContactList)) {
                    externalContactList.addAll(reqExternalContactList);
                    if(Objects.nonEmpty(batchGetByUserResponse.getNextCursor())){
                        batchGetByUserRequest.setCursor(batchGetByUserResponse.getNextCursor());
                        batchGetByUser(externalContactList, batchGetByUserRequest);
                    }
                }
            }

        }
    }

    public EmployeeMap getEmployeeByWwId(String userid) {
        return Pool.get(EmployeeMap.class, userid);
    }
}
